#include "serialportmanager.h"

SerialPortManager::SerialPortManager(QObject *parent)
    : QObject(parent)
    , m_serialPort(nullptr)
    , m_baudRate(9600)
{
    m_serialPort = new QSerialPort(this);
    connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortManager::handleReadyRead);
    connect(m_serialPort, QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::errorOccurred),
            this, &SerialPortManager::handleError);
}

SerialPortManager::~SerialPortManager()
{
    closeSerialPort();
}

QStringList SerialPortManager::getAvailablePorts()
{
    QStringList ports;
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        ports.append(info.portName());
    }
    return ports;
}

bool SerialPortManager::openSerialPort(const QString &portName, int baudRate)
{
    if (m_serialPort->isOpen()) {
        closeSerialPort();
    }

    m_serialPort->setPortName(portName);
    m_serialPort->setBaudRate(baudRate);
    m_serialPort->setDataBits(QSerialPort::Data8);
    m_serialPort->setParity(QSerialPort::NoParity);
    m_serialPort->setStopBits(QSerialPort::OneStop);
    m_serialPort->setFlowControl(QSerialPort::NoFlowControl);

    if (m_serialPort->open(QIODevice::ReadWrite)) {
        emit connectionStatusChanged(true);
        qDebug() << "串口" << portName << "打开成功,波特率:" << baudRate;
        return true;
    } else {
        emit errorOccurred(QString("无法打开串口 %1: %2").arg(portName).arg(m_serialPort->errorString()));
        return false;
    }
}

void SerialPortManager::closeSerialPort()
{
    if (m_serialPort->isOpen()) {
        m_serialPort->close();
        emit connectionStatusChanged(false);
        qDebug() << "串口已关闭";
    }
}

bool SerialPortManager::isConnected() const
{
    return m_serialPort->isOpen();
}

bool SerialPortManager::sendData(const QByteArray &data)
{
    if (!m_serialPort->isOpen()) {
        qDebug() << "串口未打开,无法发送数据";
        return false;
    }

    qint64 bytesWritten = m_serialPort->write(data);
    if (bytesWritten == -1) {
        qDebug() << "数据发送失败:" << m_serialPort->errorString();
        return false;
    }

    // 等待数据写入完成
    if (!m_serialPort->waitForBytesWritten(1000)) {
        qDebug() << "数据写入超时";
        return false;
    }

    qDebug() << "成功发送" << bytesWritten << "字节:" << data;
    return true;
}

void SerialPortManager::handleReadyRead()
{
    QByteArray data = m_serialPort->readAll();
    emit rawDataReceived(data); // 发射原始数据信号

    m_buffer.append(data);

    // 解析JSON数据
    int from = 0;
    int index = m_buffer.indexOf('\n', from);
    while (index != -1) {
        QByteArray line = m_buffer.mid(from, index - from).trimmed();
        if (!line.isEmpty()) {
            QJsonObject jsonObj = parseJsonData(line);
            if (!jsonObj.isEmpty()) {
                if (validateSensorData(jsonObj)) {
                    emit dataReceived(jsonObj);
                } else {
                    qDebug() << "数据验证失败:" << line;
                }
            }
        }
        from = index + 1;
        index = m_buffer.indexOf('\n', from);
    }
    m_buffer.remove(0, from);
}

void SerialPortManager::handleError(QSerialPort::SerialPortError error)
{
    if (error != QSerialPort::NoError && error != QSerialPort::TimeoutError) {
        QString errorMsg = m_serialPort->errorString();
        qDebug() << "串口错误:" << errorMsg;
        emit errorOccurred(errorMsg);
    }
}

QJsonObject SerialPortManager::parseJsonData(const QByteArray &data)
{
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);

    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "JSON解析错误:" << parseError.errorString() << "数据:" << data;
        return QJsonObject();
    }

    if (!doc.isObject()) {
        qDebug() << "数据不是有效的JSON对象:" << data;
        return QJsonObject();
    }

    return doc.object();
}

bool SerialPortManager::validateSensorData(const QJsonObject &data)
{
    // 验证必需字段
    if (!data.contains("device_id")) {
        return false;
    }

    // 验证可选字段的数据类型
    if (data.contains("temperature") && !data["temperature"].isDouble()) return false;
    if (data.contains("humidity") && !data["humidity"].isDouble()) return false;
    if (data.contains("light") && !data["light"].isDouble()) return false;
    if (data.contains("co2") && !data["co2"].isDouble()) return false;
    if (data.contains("pressure") && !data["pressure"].isDouble()) return false;
    if (data.contains("distance") && !data["distance"].isDouble()) return false;

    return true;
}
